gdk: Compress window state events
authorJonas Ådahl <jadahl@gmail.com>
Fri, 26 Feb 2016 06:10:06 +0000 (14:10 +0800)
committerJonas Ådahl <jadahl@gmail.com>
Wed, 2 Mar 2016 02:22:17 +0000 (10:22 +0800)
If there are already a window state event for a given window queued
when the window state is changed, drop that event and queue a new event
with a changed_mask based on the state before last event that was queue
without compression.

https://bugzilla.gnome.org/show_bug.cgi?id=762468

gdk/gdkevents.c
gdk/gdkinternals.h

index 827b03a5c2652c29e730e18a6cdc11bf2698bda1..a094d4aad3670f3b97c551d957cc146af47b507d 100644 (file)
@@ -2159,12 +2159,32 @@ _gdk_event_button_generate (GdkDisplay *display,
     }
 }
 
+static GList *
+gdk_get_pending_window_state_event_link (GdkWindow *window)
+{
+  GdkDisplay *display = gdk_window_get_display (window);
+  GList *tmp_list;
+
+  for (tmp_list = display->queued_events; tmp_list; tmp_list = tmp_list->next)
+    {
+      GdkEventPrivate *event = tmp_list->data;
+
+      if (event->event.type == GDK_WINDOW_STATE &&
+          event->event.window_state.window == window)
+        return tmp_list;
+    }
+
+  return NULL;
+}
+
 void
 _gdk_set_window_state (GdkWindow      *window,
                        GdkWindowState  new_state)
 {
+  GdkDisplay *display = gdk_window_get_display (window);
   GdkEvent temp_event;
   GdkWindowState old;
+  GList *pending_event_link;
 
   g_return_if_fail (window != NULL);
 
@@ -2173,11 +2193,22 @@ _gdk_set_window_state (GdkWindow      *window,
   temp_event.window_state.send_event = FALSE;
   temp_event.window_state.new_window_state = new_state;
 
-  old = window->state;
-
-  if (temp_event.window_state.new_window_state == old)
+  if (temp_event.window_state.new_window_state == window->state)
     return; /* No actual work to do, nothing changed. */
 
+  pending_event_link = gdk_get_pending_window_state_event_link (window);
+  if (pending_event_link)
+    {
+      old = window->old_state;
+      _gdk_event_queue_remove_link (display, pending_event_link);
+      g_list_free_1 (pending_event_link);
+    }
+  else
+    {
+      old = window->state;
+      window->old_state = old;
+    }
+
   temp_event.window_state.changed_mask = new_state ^ old;
 
   /* Actually update the field in GdkWindow, this is sort of an odd
@@ -2199,7 +2230,7 @@ _gdk_set_window_state (GdkWindow      *window,
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_TEMP: /* ? */
-      gdk_display_put_event (gdk_window_get_display (window), &temp_event);
+      gdk_display_put_event (display, &temp_event);
       break;
     case GDK_WINDOW_FOREIGN:
     case GDK_WINDOW_ROOT:
index ad1947eb21cda747eac3b2855f0cf7a18b222e27..2edc20472fc16579577bec327eab9e79ca5d918e 100644 (file)
@@ -315,6 +315,7 @@ struct _GdkWindow
   /* We store the old expose areas to support buffer-age optimizations */
   cairo_region_t *old_updated_area[2];
 
+  GdkWindowState old_state;
   GdkWindowState state;
 
   guint8 alpha;